<?php

declare(strict_types=1);

namespace App\Controller\Mini\V2\Publics;

use App\Controller\Mini\V2\Controllers;
use App\Factory\Wechat\Factory;
use App\Model\Orders\Order;
use App\Model\Users\User;
use App\Model\Users\UserOauth;
use App\Services\Orders\Order as OrderServices;
use App\Services\Users\User as UserServices;
use App\Utils\Other\Jwt\Token;
use Hyperf\Collection\Arr;
use Psr\Http\Message\ResponseInterface;
use App\Services\Users\UserOauth as UserOauthServices;
use App\Request\Publics\Login as LoginRequest;

/**
 * Class Login
 * @author zx
 * @package App\Controller\Mini\V2\Publics
 */
class Login extends Controllers
{
    /**
     * 请求类
     * @var string
     */
    protected string $requestClass = LoginRequest::class;

    public function __construct(
        protected Factory $wechatFactory,
        protected UserOauthServices $userOauthServices,
        protected OrderServices $orderServices,
        protected UserServices $userServices
    )
    {
        parent::__construct();
    }

    /**
     * 微信静默授权
     * @return ResponseInterface
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
     */
    public function oauth2(Token $token):ResponseInterface
    {
        $input = $this->input(['code', 'no']);
        $app = $this->wechatFactory->mini();

        $response = $app->getUtils()->codeToSession($input['code']);

        if (empty($response['openid'])) {
            $errorMessage = 'code2Session error: '.json_encode($response, JSON_UNESCAPED_UNICODE);
            errorLogs($errorMessage);
            return internalError($errorMessage);
        }

        // 如果之前登录过
        $tokenStr = getAuthorization();
        if ($tokenStr) {
            try {
                $data = $token->decode($tokenStr, $newToken);
                $response['user_id'] = $data['user_id'];
                $userModel = $this->userServices->with(['shop'])->findOrFail($response['user_id']);
                $response['shop'] = $userModel->shop->toArray();
            } catch (\Throwable $throwable) {}
        }

        // 处理情况一个微信多个收件人情况, 所以先判断订单是否存在
        if (Arr::get($input, 'no')) {
            /** @var Order $orderModel */
            $orderModel = $this->orderServices->with(['user', 'shop'])->where('no', $input['no'])->firstOrFail();

            /** @var User $userModel */
            $userModel = $orderModel->user;
            if (!$this->userOauthServices->where('openid', $response['openid'])->where('user_id', $userModel->id)->exists()) { // 如果授权不存在则新增用户授权
                $oauthModel = $userModel->oauth()->create([
                    'user_id' => $orderModel->user_id,
                    'shop_id' => $orderModel->shop_id,
                    'openid' => $response['openid'],
                    'unionid' => Arr::get($response, 'unionid'),
                    'is_login' => true
                ]);

                if (!$oauthModel->exists) {
                    return internalError();
                }
            }
            $response['user_id'] = $orderModel->user_id;
            $response['shop'] = $orderModel->shop->toArray();
        }

        /** @var UserOauth $userOauthModel */
        $response['users'] = $this->userOauthServices
            ->where('openid', $response['openid'])
            ->pluck('user_id'); // 查询该微信下所有用户信息

        return success([
            'token' => $token->encode($response)
        ]);
    }
}
